/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "nci_utils.h"
#include "nfc_osi_api.h"

/**
 * @file nci_utils.c
 * @brief NCI模块的工具函数
*/

/**
 * @brief 分配一个NCI_BUF结构体
 *
 * @param head NCI指令头
 * @return tNCI_BUF* 返回一个tNCI_BUF结构体指针
*/
tNCI_BUF* alloc_nci_buf(uint16_t head) {
    return alloc_nci_buf_with_cap(head, NCI_BUF_PAYLOAD_DEFAULT_SIZE);
}

/**
 * @brief 分配一个NCI_BUF结构体, 可以指定容量
 *
 * @param head NCI指令头
 * @param cap 容量
 * @return tNCI_BUF* 返回一个tNCI_BUF结构体指针
*/
tNCI_BUF* alloc_nci_buf_with_cap(uint16_t head, uint16_t cap) {
    tNCI_BUF *buf = (tNCI_BUF*) osi_calloc(sizeof(tNCI_BUF));
    if (buf == NULL) {
        return NULL;
    }
    buf->data = (uint8_t*) osi_calloc(cap);
    if (buf->data == NULL) {
        osi_free(buf);
        return NULL;
    }
    if (head != 0) {
        buf->head.hdr[0] = head >> 8;
        buf->head.hdr[1] = head & 0xFF;
    }

    buf->cap = cap;
    buf->len = 0;
    return buf;
}

/**
 * @brief 释放一个NCI_BUF结构体
 *
 * @note 释放NCI_BUF结构体时，同时也会释放其内部的raw数据
 * @note buf为NULL时，不做任何操作
 *
 * @param buf NCI_BUF结构体指针
*/
void free_nci_buf(tNCI_BUF* buf) {
    if (buf == NULL) {
        return;
    }
    if (buf->data) {
        osi_free(buf->data);
    }
    osi_free(buf);
}

/**
 * @brief 清空NCI_BUF中保存的数据
 *
 * @param buf NCI_BUF结构体指针
*/
void reset_nci_buf(tNCI_BUF *buf) {
    if (!buf) {
        return;
    }
    osi_memset_s(buf->data, buf->cap, 0, buf->len);
    buf->len  = 0;
}

/**
 * @brief 重新分配NCI_BUF的容量，已保存的数据会拷贝保留
 *
 * @note 扩容后tNCI_BUF指针不变
 *
 * @param buf NCI_BUF结构体指针
 * @param new_cap 新容量，不能和现有容量相同，且必须大于已保存数据的长度
*/
bool realloc_nci_buf(tNCI_BUF *buf, uint16_t new_cap) {
    if (!buf) {
        return false;
    }
    if (buf->cap == new_cap || buf->len > new_cap) {
        return false;
    }
    uint8_t *new_data = (uint8_t*) osi_calloc(new_cap);
    if (new_data == NULL) {
        return false;
    }
    if (!osi_memcpy_s(new_data, new_cap, buf->data, buf->len)) {
        osi_free(new_data);
        return false;
    }
    osi_free(buf->data);
    buf->data = new_data;
    buf->cap = new_cap;
    return true;
}
